package com.wang.springbootinit.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.wang.springbootinit.common.ErrorCode;
import com.wang.springbootinit.constant.BISystemEnum;
import com.wang.springbootinit.constant.UserConstant;
import com.wang.springbootinit.exception.BusinessException;
import com.wang.springbootinit.mapper.ChatHistoryMapper;
import com.wang.springbootinit.model.entity.ChatHistory;
import com.wang.springbootinit.model.entity.User;
import com.wang.springbootinit.model.param.ChatHistoryParam;
import com.wang.springbootinit.model.vo.ChatHistoryVO;
import com.wang.springbootinit.service.ChatHistoryService;
import com.wang.springbootinit.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 聊天记录
 */
@Service("ChatHistoryService")
@Slf4j
public class ChatHistoryServiceImpl extends ServiceImpl<ChatHistoryMapper, ChatHistory>
        implements ChatHistoryService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ChatHistoryServiceImpl.class);

    @Resource
    private UserService userService;

    @Value("${pdf.storage.path}")
    private String pdfStoragePath;

    /**
     * 保存消息体
     * @param chatHistory
     * @return Boolean
     */
    @Override
    public boolean saveChatHistory(ChatHistory chatHistory) {
        if(ObjectUtil.isNull(chatHistory)){
            LOGGER.error("聊天记录实体类为null");
            return false;
        }
        return this.save(chatHistory);
    }

    /**
     * 批量保存聊天记录
     * @param chatHistories
     * @return Boolean
     */
    @Override
    public boolean saveChatHistories(List<ChatHistory> chatHistories) {
        if(CollectionUtil.isEmpty(chatHistories)){
            return false;
        }
        boolean result = false;
        for (ChatHistory chatHistory : chatHistories) {
            result = this.saveChatHistory(chatHistory);
        }
        return result;
    }

    /**
     * 聊天记录列表
     * @param param
     * @return List<ChatHistoryVO>
     */
    @Override
    public List<ChatHistoryVO> listByParam(ChatHistoryParam param, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(BISystemEnum.NOLOGIN.getCode(), BISystemEnum.NOLOGIN.getMsg());
        }
        boolean isAdmin = ObjectUtil.equal(loginUser.getUserRole(), UserConstant.ADMIN_ROLE);

        //如果是管理员，则查全部，如果是普通用户，只查自己的
        LambdaQueryWrapper<ChatHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ChatHistory::getId, ChatHistory::getConversationId);
        if(!isAdmin){
            queryWrapper.eq(ChatHistory::getUserId, loginUser.getId());
        }
        if(StrUtil.isNotBlank(param.getKeyword())){
            queryWrapper.like(ChatHistory::getChatInfo,param.getKeyword());
        }
        if(ObjectUtil.isNotNull(param.getStartDate())){
            queryWrapper.ge(ChatHistory::getCreateTime, param.getStartDate());
        }
        if(ObjectUtil.isNotNull(param.getEndDate())){
            queryWrapper.le(ChatHistory::getCreateTime, param.getEndDate());
        }
        queryWrapper.eq(ChatHistory::getSort,0);
        if(ObjectUtil.isNotNull(param.getConversationId())){
            queryWrapper.eq(ChatHistory::getConversationId, param.getConversationId());
        }else {
            queryWrapper.orderByDesc(ChatHistory::getCreateTime);
        }
        queryWrapper.groupBy(ChatHistory::getConversationId, ChatHistory::getId);
        List<ChatHistory> chatHistoryList = this.list(queryWrapper);
        if(CollectionUtil.isEmpty(chatHistoryList)){
            return Collections.emptyList();
        }

        List<Long> chatHistoryIds = chatHistoryList.stream().map(ChatHistory::getId).distinct().collect(Collectors.toList());
        List<ChatHistory> chatHistories = listByIds(chatHistoryIds);
        return chatHistories.stream().map(item -> {
            ChatHistoryVO chatHistoryVO = new ChatHistoryVO();
            chatHistoryVO.setId(item.getId());
            chatHistoryVO.setSort(item.getSort());
            chatHistoryVO.setConversationId(item.getConversationId());
            chatHistoryVO.setChatUserType(item.getChatUserType());
            chatHistoryVO.setChatInfo(item.getChatInfo());
            chatHistoryVO.setCreateTime(item.getCreateTime());
            chatHistoryVO.setUserName(loginUser.getUserName());
            return chatHistoryVO;
        }).collect(Collectors.toList());
    }

    /**
     * 详情
     * @param param
     * @param request
     * @return
     */
    @Override
    public List<ChatHistoryVO> detail(ChatHistoryParam param, HttpServletRequest request) {
        if(StrUtil.isEmpty(param.getConversationId())){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(BISystemEnum.NOLOGIN.getCode(), BISystemEnum.NOLOGIN.getMsg());
        }

        LambdaQueryWrapper<ChatHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatHistory::getConversationId, param.getConversationId());
        queryWrapper.eq(ChatHistory::getIsDeleted,0);
        queryWrapper.orderByAsc(ChatHistory::getSort);
        List<ChatHistory> chatHistoryList = list(queryWrapper);
        return chatHistoryList.stream().map(item -> {
            ChatHistoryVO chatHistoryVO = new ChatHistoryVO();
            chatHistoryVO.setId(item.getId());
            chatHistoryVO.setConversationId(item.getConversationId());
            chatHistoryVO.setChatInfo(item.getChatInfo());
            chatHistoryVO.setChatUserType(item.getChatUserType());
            chatHistoryVO.setSort(item.getSort());
            chatHistoryVO.setCreateTime(item.getCreateTime());
            return chatHistoryVO;
        }).collect(Collectors.toList());
    }

    @Override
    public void generatePdf(String  conversationId, HttpServletRequest request, HttpServletResponse response) {
        Document document = null;
        PdfWriter writer = null;
        try {
            // 获取聊天记录
            ChatHistoryParam param = new ChatHistoryParam();
            param.setConversationId(conversationId);
            List<ChatHistoryVO> chatHistories = this.detail(param, request);
            if (chatHistories == null || chatHistories.isEmpty()) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到聊天记录");
            }
            log.info("获取到{}条聊天记录", chatHistories.size());

            String fileName = "chat_history_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".pdf";
            response.setContentType("application/pdf");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

            // 创建PDF文档
            document = new Document();
            writer = PdfWriter.getInstance(document, response.getOutputStream());

            // 加载字体文件
            BaseFont baseFont;
            try {
                // 尝试从资源文件加载字体
                java.net.URL fontUrl = this.getClass().getClassLoader().getResource("fonts/simsun.ttc");
                if (fontUrl != null) {
                    String fontPath = URLDecoder.decode(fontUrl.getPath(), "UTF-8");
                    baseFont = BaseFont.createFont(fontPath + ",0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                } else {
                    // 如果找不到资源文件，尝试使用系统字体
                    try {
                        baseFont = BaseFont.createFont("C:/Windows/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                    } catch (Exception e) {
                        baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                    }
                }
            } catch (Exception e) {
                log.warn("无法加载中文字体，将使用默认字体: {}", e.getMessage());
                baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
            }

            Font chineseFont = new Font(baseFont, 12, Font.NORMAL);
            Font titleFont = new Font(baseFont, 16, Font.BOLD);

            // 打开文档
            document.open();

            // 添加标题
            Paragraph title = new Paragraph("聊天记录", titleFont);
            title.setAlignment(Element.ALIGN_CENTER);
            document.add(title);
            document.add(new Paragraph("\n"));

            // 添加聊天内容
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (ChatHistoryVO chat : chatHistories) {
                // 添加分隔线
                document.add(new Paragraph("----------------------------------------", chineseFont));
                
                // 添加时间
                if (chat.getCreateTime() != null) {
                    Paragraph time = new Paragraph(sdf.format(chat.getCreateTime()), chineseFont);
                    document.add(time);
                }
                
                // 添加角色和内容
                String role = "AI".equals(chat.getChatUserType()) ? "AI" : "用户";
                Paragraph content = new Paragraph(role + ": " + chat.getChatInfo(), chineseFont);
                document.add(content);
                document.add(new Paragraph("\n"));
            }

            log.info("PDF内容写入完成");
            
        } catch (Exception e) {
            log.error("生成PDF失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成PDF失败: " + e.getMessage());
        } finally {
            try {
                if (document != null) {
                    if (document.isOpen()) {
                        document.close();
                    }
                }
                if (writer != null) {
                    writer.close();
                }
                response.getOutputStream().flush();
            } catch (Exception e) {
                log.error("关闭PDF文档或输出流失败", e);
            }
        }
    }
}
